import {
  BadRequestException,
  Body,
  Controller,
  Delete,
  Get,
  Logger,
  Post,
  Put,
  Query,
} from '@nestjs/common';
import {ApiOperation, ApiTags, ApiHideProperty, ApiExcludeController, ApiBearerAuth, ApiExcludeEndpoint, ApiBody} from '@nestjs/swagger';

import {ApiResult} from '~/common/decorators/api-result.decorator';
import {IdParam} from '~/common/decorators/id-param.decorator';
import {Perm, definePermission} from '~/modules/auth/decorators/permission.decorator';
import {RoleEntity} from '~/modules/system/role/role.entity';

import {MenuService} from '../menu/menu.service';

import {RoleBindDto, RoleDto, RoleQueryDto, RoleUpdateDto} from './role.dto';
import {RoleInfo} from './role.model';
import {RoleService} from './role.service';
import { Public } from '~/modules/auth/decorators/public.decorator';
import { AllowAnon } from '~/modules/auth/decorators/allow-anon.decorator';

export const permissions = definePermission('system:role', {
  LIST: 'list',
  CREATE: 'create',
  READ: 'read',
  UPDATE: 'update',
  DELETE: 'delete',
} as const);

@ApiTags('Role - 角色模块')
@ApiBearerAuth()
@Controller('role')
export class RoleController {
	private readonly logger = new Logger(RoleController.name);

  constructor(
    private roleService: RoleService,
    private menuService: MenuService,
  ) {}

	@ApiExcludeEndpoint()
  @Get()
  @ApiOperation({summary: '获取角色列表'})
  @ApiResult({type: [RoleEntity], isPage: true})
  @Perm(permissions.LIST)
  async list(@Query() dto: RoleQueryDto) {
    return this.roleService.list(dto);
  }

	@ApiExcludeEndpoint()
  @Get(':id')
  @ApiOperation({summary: '获取角色信息'})
  @ApiResult({type: RoleInfo})
  @Perm(permissions.READ)
  async info(@IdParam() id: number) {
    return this.roleService.info(id);
  }

	@ApiExcludeEndpoint()
	@Public()
  @Post()
  @ApiOperation({summary: '新增角色'})
	@ApiBody({type: RoleDto})
  // @Perm(permissions.CREATE)
  async create(@Body() dto: RoleDto): Promise<void> {
    await this.roleService.create(dto);
  }

	@ApiExcludeEndpoint()
  @Put(':id')
  @ApiOperation({summary: '更新角色'})
  @Perm(permissions.UPDATE)
  async update(@IdParam() id: number, @Body() dto: RoleUpdateDto): Promise<void> {
    await this.roleService.update(id, dto);
    await this.menuService.refreshOnlineUserPerms(false);
    // this.sseService.noticeClientToUpdateMenusByRoleIds([id]);
  }

	@ApiExcludeEndpoint()
  @Delete(':id')
  @ApiOperation({summary: '删除角色'})
  @Perm(permissions.DELETE)
  async delete(@IdParam() id: number): Promise<void> {
    if (await this.roleService.checkUserByRoleId(id))
      throw new BadRequestException('该角色存在关联用户，无法删除');

    await this.roleService.delete(id);
    await this.menuService.refreshOnlineUserPerms(false);
    // this.sseService.noticeClientToUpdateMenusByRoleIds([id]);
  }

	@Public()
	@AllowAnon()
	@ApiHideProperty()
	@Post('/root')
	@ApiOperation({summary: '新增角色'})
	async createByRoot(@Body() dto: RoleDto): Promise<RoleEntity> {
		this.logger.log('createByRoot', dto);
		return await this.roleService.createByRoot(dto);
	}

	@Public()
	@Post('bind')
	@ApiOperation({summary: '为用户绑定角色'})
	@ApiBody({type: RoleBindDto})
	// @Perm(permissions.UPDATE)
	async bind(@Body() dto: RoleBindDto): Promise<void> {
		await this.roleService.bindUserToRoles(dto.userId, dto.roleId);
	}
}
